/*
 * @Description: 
 * @Version: 1.0
 * @Autor: ziwei
 * @Date: 2021-05-16 09:36:07
 * @LastEditors: ziwei
 * @LastEditTime: 2021-06-30 12:00:34
 */
import { compileToFunction } from "./compiler/index";
import { initGlobalAPI } from "./global-api/index";

import { initMixin } from "./init";
import { lifeCycleMixin } from "./observe/lifecycle";
import { renderMixin } from "./render";
import { createElm, patch } from "./vdom/patch";
//vue 要如何实现 原型模式 所有的功能都通过原型扩展的方式来添加
function Vue(options) {
  debugger
    //实现vue的初始化功能
    this._init(options);
}
debugger
initMixin(Vue);
renderMixin(Vue);
lifeCycleMixin(Vue)

initGlobalAPI(Vue)

//先生成一个虚拟节点,就是vue的初始化流程
/* let vm = new Vue({
  data(){
    return {name:'jw'}
  }
})
let render = compileToFunction('<div>{{name}}</div>')
let oldVnode = render.call(vm);//第一次的虚拟节点
let el1 = createElm(oldVnode);
document.body.appendChild(el1);

//在生成一个新的虚拟节点 patch
vm.name = "zf"
let newVnode = render.call(vm);//第一次的虚拟节点

setTimeout(() => {
  patch(oldVnode,newVnode);
}, 2000);
console.log(oldVnode, newVnode); */


//导出给别人使用
export default Vue

//1 new Vue会调用——int方法进行初始化操作
//2 会将用户的选项放到vm.options上
// 3.会对当前属性上搜索有没有data数据 initSate
//4.有data,判断dadta是不是一个函数，如果是函数返回值initData
//5.observe去观测data中的数据和vm没关系 说明data已经变成了响应式
//6.vm上取值也能取到data中的数据 vm._data = data  这样用户能取到data vm._data
//7.用户觉得有点麻烦 vm.xxx => vm._data

//8.如果更新对象不存在的属性，会导致摄图不更新 如果数据更新索引和长度不会触发更新

//如果有el需要挂载到页面上
//如果是数组更新
//9. 如果是替换成一个新对象，新对象会被劫持，如果数据存放新内容 push unshift()新增的内容也会被劫持
//通过__obj__进行标识这个对象被监控过（在vue中被监控的对象身上都有一个__ob__这个属性上）
//10 如果你就想改索引 可以使用$set方法 内部就是splice



//更新流程 依赖收集总结：只有跟组件的情况
//1.vue里面用到了观察者模式，默认组件渲染的时候 会创建一个watcher(并且会渲染视图)
//2.当渲染视图的时候，回到data的数据，会走这个属性的get方法，就让这个属性的dep记录watcher
//3.同时让watcher也己住dep(这个逻辑目前没用到) dep和watcher是多对多的关系 因为属性可能对应多个视图 一个视图对应多个数据
//4.如果数据发生变化，会通知对应的dep，依次通知watcher


// 组件流程
/* 
1:Vue.component 注册成为全局组件 内部会自动调用 Vue.extend方法，返回组件的构造函数
2：组件初始化的时候，会做一个合并mergeOptions(自己的组件._proto_ = 全局的组件)
3：内部会对模板进行编译操作 _c('组件的名字') 会做筛查  如果是组件就创造一个组件的虚拟节点,还会判断Ctor 如果是对象 会调用Vue.extend,所有的组件都是通过Vue.exteng方法来实现的（componentOptions里面放着所有内容 属性的实现 时间的实现 插槽的内容 Ctor）
 */
//4. 创建组件真实节点(new Ctor 拿到组件的实例 并且调用组件的$.mount(会生成一个$el 对应组件模板渲染后的结果)) vnode.componentInstance = new Ctor() vnode.component.$el=>组件渲染后的结果
//5 将组件的vnode.componentInstance.$el插入到父标签中

//6.组件的new Ctor() 会进行组件的初始化，给组件再次添加一个独立渲染watcher（因为组件渲染时 组件对应的属性会收集自己的渲染watcher）